package jkadx.core;

/* Copyright 2009 Anthony Surma
This file is part of Java's Kademlia Extension (JKADX).

JKADX is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
any later version.

JKADX is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with JKADX.  If not, see <http://www.gnu.org/licenses/>.
 */

import jkadx.xml.ElementNode;
import jkadx.xml.XML;
import java.io.*;
import java.util.Scanner;
import org.jdom.*;
import java.net.*;
import java.util.ArrayList;
import jkadx.dht.UniqueId;

// Make this more generic, probably with a string file named <settingsFilename>str.xml or whatever
// Seriously rethink this class!
/**
 *
 * @author Anthony Surma
 */
public final class CoreConfig
{
    final static String APP_NAME    = "core";
    final static String SAVE_FOLDER = "config"; // i.n. <user's home>/jkadx/core/config
    final static String USER_HOME   = System.getProperty("user.home");
    final static String SEPARATOR   = File.separator;    
    final static File   PATH        = new File(USER_HOME + SEPARATOR + "jkadx" +
                                              SEPARATOR + APP_NAME + SEPARATOR + SAVE_FOLDER);
    final        File   settingsFile;
    final        File   backupSettingsFile;
    final        String settingsFilename;

    final ArrayList<ElementNode> theseSettings;

    public CoreConfig(String settingsFilename, String contactsFilename, int inPort, int outPort)
    {
        
        String temp[] = settingsFilename.split("\\.", 2);        	
	String input = null;
	String externalIpAddress = null;
        String s = null;
	Document settingsData;
	Scanner scan;
	Element root;
	Element element;
	UniqueId nodeid;        

        if (!PATH.isDirectory())
            PATH.mkdirs();
        settingsFile          = new File(PATH, temp[0] + ".cfg");
        backupSettingsFile    = new File(PATH, temp[0] + ".bak");
        this.settingsFilename = temp[0];

	if (settingsFile.exists())
	{
	    settingsData = XML.loadFromFile(settingsFile);
	    theseSettings = XML.toArrayList(settingsData);
	}
	else
	{
	    //System.out.println("Creating a new " + settingsFilename + " file...\n");
	    scan = new Scanner(System.in);	   
	    root = new Element("Settings");
	    settingsData = new Document(root, new DocType("Settings"));
	    root.setText("User settings for Core");
	    //System.out.print("External IP Address: ");
	    externalIpAddress = discoverExternalIpAddress();
	    //System.out.println(externalIpAddress);
	    element = new Element("externalIpAddress");
	    element.setText(externalIpAddress);
	    root.addContent(element);	   	    
	    //System.out.print(UniqueId.NBITS + "-bit NodeID: ");
	    nodeid = UniqueId.newRandom();
	    //System.out.println(nodeid);
	    element = new Element("thisNodeId");
	    element.setText(nodeid.toString());
	    root.addContent(element);
            if ((inPort | outPort) < 0)
                System.out.println("\nType in the following information, then press the ENTER key:\n");
            element = new Element("incomingPort");
            if (inPort < 0)
            {
                System.out.print("Incoming Port #: ");
                input = scan.nextLine();
                element.setText(input);
            }
            else
            {
                element.setText(String.valueOf(inPort));
            }
	    root.addContent(element);
            element = new Element("outgoingPort");
            if (outPort < 0)
            {
                System.out.print("Outgoing UDP Port #: ");
                input = scan.nextLine();
                element.setText(input);
            }
            else
            {
                element.setText(String.valueOf(outPort));
            }
	    root.addContent(element);	    
	    XML.saveToFile(settingsFile, settingsData);   //save the file to disk
	    theseSettings = XML.toArrayList(settingsData); // puts the data from config.xml into an theseSettings
	}
    }
    
    static String discoverExternalIpAddress()
    {
	String ipaddress = null;

	try
	{
	    URL url = new URL("http://checkip.dyndns.org:80/index.html");
	    BufferedReader bufferedreader = new BufferedReader(new InputStreamReader(url.openStream()));
            // timeout??
	    ipaddress = bufferedreader.readLine();
	    ipaddress = ipaddress.substring(ipaddress.indexOf(':') + 2);
	    ipaddress = ipaddress.substring(0, ipaddress.indexOf('<'));
	    bufferedreader.close();
	}
	catch (MalformedURLException e)
	{
	    e.printStackTrace();
	}
	catch (IOException e)
	{
	    e.printStackTrace();
	}
	return ipaddress;
    }

    public ArrayList<ElementNode> getSettings()
    {
	return theseSettings;
    }

    void setNewExternalIpAddress(final String newExternalIpAddress)
    {
        ElementNode.setDataFor("externalIpAddress", newExternalIpAddress, theseSettings);
    }

    boolean saveSettings()
    {        
        final Element root = new Element("Settings");
        final Document settingsData = new Document(root, new DocType("Settings"));
        final File tempFile;
        Element element;
        
        try
        { // Create a temporary file; set it to with deleteOnExit(true);
            (tempFile = File.createTempFile(settingsFilename, null)).deleteOnExit();
        } catch (IOException ex) { return false; }
	root.setText("User settings for Core");
        for (ElementNode n : theseSettings)
        {
            element = new Element(n.getName());
            element.setText(n.getData());
            root.addContent(element);
        }
        XML.saveToFile(tempFile, settingsData); // Write the user data to this temporary file.
        
        if (backupSettingsFile.exists()) 
            backupSettingsFile.delete(); // Delete the backup file if it exists;
        settingsFile.renameTo(backupSettingsFile);  // Rename the user's previous file to <>.bak;
        tempFile.renameTo(settingsFile); // Rename the temporary file to the saveSettings file.
        return true;
    }

    // Probably never need this?
    // May be useful to check if it is the same as WANIP to know if a router/firewall exists?
  /*  static String getLANIP()
    {
	String externalIpAddress = null;
	try
	{
	    externalIpAddress = InetAddress.getLocalHost().getHostAddress();
	}
	catch (UnknownHostException n)
	{
	    n.printStackTrace();
	}
	return externalIpAddress;
    }*/
}